home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
networke
/
civ-0.000
/
civ-0
/
civ-0.3
/
src
/
server.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1995-11-17
|
5KB
|
223 lines
#ifndef MS_WIN
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#else
#include <winsock.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "defs.h"
#include "server.h"
#include "graph.h"
#include "MsgQ.h"
#include "net.h"
struct PlayerInfo
{
char *name;
int fd;
int route;
int id;
};
static PlayerInfo *playerTable;
static int connSock;
static int leftToConnect;
const int ConnectPort = 7123;
// clients use this socket to communicate with the server
int sock;
// q is NULL
static void NewConnection(MsgQ *q, int fd, int info)
{
static int currPlayer = 1;
struct sockaddr_in sock_in;
int tmp, new_sock;
tmp = sizeof(sock_in);
new_sock = accept(fd, (struct sockaddr *)&sock_in, &tmp);
if (new_sock < 0) return;
if (currPlayer >= numPlayers) {
#ifdef MS_WIN
closesocket(new_sock);
#else
close(new_sock);
#endif
return;
}
int set = 1;
setsockopt(new_sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&set, sizeof(set));
playerTable[currPlayer].fd = new_sock;
playerTable[currPlayer].route = -1;
playerTable[currPlayer].id = currPlayer;
screen->AddReadNotify(new_sock, ServerGotData, currPlayer);
++currPlayer;
}
void InitServer()
{
playerTable = new PlayerInfo[numPlayers];
playerTable[0].name = myName;
playerTable[0].fd = -1;
playerTable[0].route = -1;
playerTable[0].id = 0;
leftToConnect = numPlayers-1;
struct sockaddr_in sock_in;
int val;
sock_in.sin_addr.s_addr = htonl(INADDR_ANY);
sock_in.sin_port = htons(ConnectPort);
sock_in.sin_family = AF_INET;
if ((connSock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket failed\n");
exit(1);
}
val = 1;
if (setsockopt(connSock, SOL_SOCKET, SO_REUSEADDR, (char *)&val,
sizeof(val)) < 0) {
fprintf(stderr, "setsockopt failed\n");
exit(1);
}
if (bind(connSock, (struct sockaddr *)&sock_in, sizeof(sock_in)) < 0) {
fprintf(stderr, "bind failed\n");
exit(1);
}
if (listen(connSock, 5) < 0) {
fprintf(stderr, "listen failed\n");
exit(1);
}
screen->AddReadNotify(connSock, NewConnection, 0, 0);
}
void ServerGotData(MsgQ *q, int fd, int player)
{
static int waitingOnSynch = 0;
long cmd, arg;
int i;
if (!q->IsCmd(cmd, arg)) {
if (playerTable[player].route == -1) { // send to everyone
MsgQ *copy = NULL;
int sendsLeft = numPlayers-1;
if (player != 0) {
--sendsLeft;
copy = q->Copy();
}
if (sendsLeft == 0)
delete q;
for (i = 1; i < numPlayers; ++i)
if (i != player) {
--sendsLeft;
if (sendsLeft >= 1)
NonDestructiveSendQ(playerTable[i].fd, q);
else
SendQ(playerTable[i].fd, q);
}
if (player != 0)
HandleMessage(copy, -1, 0);
return;
}
// send to specific player
if (playerTable[player].route == 0)
HandleMessage(q, -1, 0);
else {
for (int i = 0;;++i)
if (playerTable[i].id == playerTable[player].route) {
SendQ(playerTable[i].fd, q);
break;
}
}
return;
}
// the message is a command
MsgQ *send;
switch (cmd) {
case GET_PLAYER_INFO:
delete q;
send = new MsgQ;
*send << "player_info";
*send << numPlayers;
for (i = 0; i < numPlayers; ++i)
*send << playerTable[i].name;
if (player == 0)
HandleMessage(send, -1, 0);
else
SendQ(playerTable[player].fd, send);
return;
case CHANGE_ROUTE:
delete q;
playerTable[player].route = arg;
return;
case SYNCH:
delete q;
if (waitingOnSynch == 0) // initiated synchronise
waitingOnSynch = numPlayers-1;
else {
--waitingOnSynch;
if (waitingOnSynch == 0) {
send = new MsgQ;
*send << "synch";
for (i = 1; i < numPlayers; ++i)
if (i == numPlayers-1)
SendQ(playerTable[i].fd, send);
else
NonDestructiveSendQ(playerTable[i].fd, send);
send = new MsgQ;
*send << "synch";
HandleMessage(send, -1, 0);
}
}
return;
case CONNECT:
*q >> playerTable[player].name;
delete q;
if (--leftToConnect <= 0) {
send = new MsgQ;
*send << "send_map";
HandleMessage(send, -1, 0);
}
return;
case RECONNECT:
*q >> playerTable[player].name;
delete q;
playerTable[player].id = arg;
--leftToConnect;
return;
}
delete q;
return;
}
// client calls this to connect to us
void ConnectServer(char *server)
{
struct sockaddr_in addr;
struct hostent FAR *host;
addr.sin_port = htons(ConnectPort);
host = gethostbyname(server);
if (host == NULL) {
exit(1);
}
addr.sin_addr = *(struct in_addr *)host->h_addr;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
exit(1);
}
addr.sin_family = AF_INET;
if (connect(sock, (sockaddr *)&addr, sizeof(addr)) < 0) {
exit(1);
}
}